package com.ruoyi.ldzlsb.service.impl;

import java.util.List;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.ldzlsb.domain.SbRepairApplication;
import com.ruoyi.ldzlsb.mapper.SbRepairApplicationMapper;
import com.ruoyi.ldzlsb.service.ISbRepairApplicationService;
import com.ruoyi.common.security.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.ldzlsb.domain.SbRepairOrder;
import com.ruoyi.ldzlsb.service.ISbRepairOrderService;
import com.ruoyi.common.core.utils.SpringUtils;
import com.ruoyi.ldzlsb.service.ISbEquipmentService;

/**
 * 设备报修单Service业务层处理
 * 
 * @author ruoyi
 */
@Service
public class SbRepairApplicationServiceImpl implements ISbRepairApplicationService 
{
    private static final Logger log = LoggerFactory.getLogger(SbRepairApplicationServiceImpl.class);
    
    @Autowired
    private SbRepairApplicationMapper repairApplicationMapper;

    /**
     * 查询设备报修单
     * 
     * @param repairId 设备报修单主键
     * @return 设备报修单
     */
    @Override
    public SbRepairApplication getById(Integer repairId)
    {
        SbRepairApplication application = repairApplicationMapper.selectSbRepairApplicationById(repairId);
        if (application != null) {
            // 设置兼容ID字段
            application.setId(application.getRepairId());
        }
        return application;
    }
    
    /**
     * 查询设备报修单列表
     * 
     * @param application 设备报修单
     * @return 设备报修单
     */
    @Override
    public List<SbRepairApplication> findRepairApplication(SbRepairApplication application)
    {
        List<SbRepairApplication> list = repairApplicationMapper.selectSbRepairApplicationList(application);
        // 设置兼容ID字段
        for (SbRepairApplication item : list) {
            item.setId(item.getRepairId());
        }
        return list;
    }

    /**
     * 新增设备报修单
     * 
     * @param application 设备报修单
     * @return 结果
     */
    @Override
    public boolean saveRepairApplication(SbRepairApplication application)
    {
        try {
            log.info("开始新增报修单: equipmentId={}, equipmentName={}", application.getEquipmentId(), application.getEquipmentName());
            
            // 检查设备是否已经在报修中
            if (application.getEquipmentId() != null) {
                SbRepairApplication query = new SbRepairApplication();
                query.setEquipmentId(application.getEquipmentId());
                query.setStatus("pending"); // 检查待处理状态
                List<SbRepairApplication> existingApplications = repairApplicationMapper.selectSbRepairApplicationList(query);
                
                if (!existingApplications.isEmpty()) {
                    log.warn("设备ID {} 已有待处理的报修单，不允许重复报修", application.getEquipmentId());
                    throw new RuntimeException("该设备已有待处理的报修单，请等待处理完成或取消后再报修");
                }
                
                // 检查处理中状态
                query.setStatus("processing");
                existingApplications = repairApplicationMapper.selectSbRepairApplicationList(query);
                
                if (!existingApplications.isEmpty()) {
                    log.warn("设备ID {} 已有处理中的报修单，不允许重复报修", application.getEquipmentId());
                    throw new RuntimeException("该设备已有处理中的报修单，请等待处理完成后再报修");
                }
            }
            
            // 设置基本信息
            application.setCreateTime(DateUtils.getNowDate());
            application.setCreateBy(SecurityUtils.getUsername());
            
            // 确保报修时间有值
            if (application.getReportTime() == null) {
                application.setReportTime(DateUtils.getNowDate());
            }
            
            // 日志输出报修人和手机号
            log.info("报修人: {}, 手机号: {}", application.getReportPerson(), application.getReportPhone());
            
            // 确保手机号有值（如果前端没有传递，则设置为空字符串而非null）
            if (application.getReportPhone() == null) {
                application.setReportPhone("");
                log.warn("报修人手机号为null，已设置为空字符串");
            }
            
            // 生成报修单编号
            if (application.getRepairCode() == null || application.getRepairCode().isEmpty()) {
                // 允许重试3次，以防并发导致编号重复
                for (int attempt = 0; attempt < 3; attempt++) {
                    try {
                        R<String> codeResult = generateCode();
                        if (codeResult.getCode() == 200) {
                            application.setRepairCode(codeResult.getData());
                            log.info("生成报修单编号: {}", application.getRepairCode());
                            break;
                        } else {
                            log.warn("生成报修单编号失败，尝试重试...");
                        }
                    } catch (Exception e) {
                        log.error("生成报修单编号异常，尝试重试: {}", e.getMessage());
                        // 最后一次尝试失败，使用时间戳作为唯一编号
                        if (attempt == 2) {
                            String timestamp = String.valueOf(System.currentTimeMillis());
                            application.setRepairCode("REP" + DateUtils.dateTimeNow("yyyyMMdd") + timestamp.substring(timestamp.length() - 8));
                            log.info("使用备用方案生成报修单编号: {}", application.getRepairCode());
                        }
                    }
                    // 短暂延迟，减少并发冲突
                    Thread.sleep(50);
                }
                
                // 最终检查，如果编号仍然为空，则使用最后的备用方案
                if (application.getRepairCode() == null || application.getRepairCode().isEmpty()) {
                    String timestamp = String.valueOf(System.currentTimeMillis());
                    application.setRepairCode("REP" + DateUtils.dateTimeNow("yyyyMMddHHmmss") + timestamp.substring(timestamp.length() - 4));
                    log.info("使用最终备用方案生成报修单编号: {}", application.getRepairCode());
                }
            }
            
            // 设置状态默认值
            if (application.getStatus() == null) {
                application.setStatus("pending");
            }
            
            // 设置优先级默认值
            if (application.getPriority() == null) {
                application.setPriority("normal");
            }
            
            // 设置删除标记默认值
            if (application.getIsDelete() == null) {
                application.setIsDelete("0");
            }
            
            // 检查故障描述
            if (application.getFaultDescription() == null || application.getFaultDescription().isEmpty()) {
                if (application.getRemark() != null && !application.getRemark().isEmpty()) {
                    application.setFaultDescription(application.getRemark());
                } else {
                    application.setFaultDescription("未提供故障描述");
                }
            }
            
            // 添加测试数据作为示例
            if (repairApplicationMapper.selectSbRepairApplicationList(new SbRepairApplication()).isEmpty()) {
                try {
                    addTestData();
                } catch (Exception e) {
                    log.warn("添加测试数据失败，但不影响业务流程: {}", e.getMessage());
                }
            }
            
            // 尝试插入数据
            int maxRetries = 2;
            int retries = 0;
            while (retries <= maxRetries) {
                try {
                    int rows = repairApplicationMapper.insertSbRepairApplication(application);
                    if (rows > 0) {
                        log.info("新增报修单成功: repairId={}, repairCode={}", application.getRepairId(), application.getRepairCode());
                        
                        // 自动更新设备状态为维修中
                        if (application.getEquipmentId() != null) {
                            updateEquipmentStatusToRepair(application.getEquipmentId());
                        }
                        
                        return true;
                    } else {
                        log.error("新增报修单失败: 数据库插入返回0行");
                        return false;
                    }
                } catch (Exception e) {
                    if (e.getMessage().contains("Duplicate entry") && e.getMessage().contains("uk_repair_code")) {
                        log.warn("报修单编号重复，重新生成编号后重试: {}", e.getMessage());
                        String timestamp = String.valueOf(System.currentTimeMillis());
                        application.setRepairCode("REP" + DateUtils.dateTimeNow("yyyyMMddHHmmss") + timestamp.substring(timestamp.length() - 6));
                        log.info("重新生成报修单编号: {}", application.getRepairCode());
                        retries++;
                    } else {
                        log.error("新增报修单失败，异常不可恢复", e);
                        throw e;
                    }
                }
            }
            
            log.error("新增报修单失败: 达到最大重试次数");
            return false;
        } catch (Exception e) {
            log.error("新增报修单失败", e);
            throw new RuntimeException("新增报修单失败: " + e.getMessage(), e);
        }
    }

    /**
     * 修改设备报修单
     * 
     * @param application 设备报修单
     * @return 结果
     */
    @Override
    public boolean updateRepairApplication(SbRepairApplication application)
    {
        try {
            application.setUpdateTime(DateUtils.getNowDate());
            application.setUpdateBy(SecurityUtils.getUsername());
            return repairApplicationMapper.updateSbRepairApplication(application) > 0;
        } catch (Exception e) {
            log.error("修改报修单失败", e);
            return false;
        }
    }

    /**
     * 删除设备报修单信息
     * 
     * @param repairId 设备报修单主键
     * @return 结果
     */
    @Override
    public boolean deleteRepairApplication(Integer repairId)
    {
        try {
            return repairApplicationMapper.deleteSbRepairApplicationById(repairId) > 0;
        } catch (Exception e) {
            log.error("删除报修单失败", e);
            return false;
        }
    }

    /**
     * 生成报修单编号
     */
    @Override
    public R<String> generateCode() {
        try {
            // 查询当前最大序列号
            long maxCode = repairApplicationMapper.selectMaxRepairCode();
            // 当前日期格式化为yyyyMMdd
            String dateCode = DateUtils.dateTimeNow("yyyyMMdd");
            // 格式：REP + 日期 + 4位序号（从0001开始）
            String code = "REP" + dateCode + String.format("%04d", maxCode + 1);
            log.info("生成报修单编号: {}", code);
            
            // 检查编号是否已存在（防止并发问题导致重复）
            boolean exists = checkRepairCodeExists(code);
            if (exists) {
                // 如果编号已存在，使用时间戳作为后缀确保唯一性
                String uniqueSuffix = String.valueOf(System.currentTimeMillis()).substring(8);
                code = "REP" + dateCode + String.format("%04d", maxCode + 1) + uniqueSuffix;
                log.info("生成唯一报修单编号: {}", code);
            }
            
            return R.ok(code);
        } catch (Exception e) {
            log.error("生成报修单编号失败", e);
            // 如果查询失败，使用时间戳生成唯一编号（包含毫秒）
            String timestamp = String.valueOf(System.currentTimeMillis());
            String code = "REP" + DateUtils.dateTimeNow("yyyyMMdd") + timestamp.substring(timestamp.length() - 4);
            return R.ok(code);
        }
    }
    
    /**
     * 检查报修单编号是否已存在
     */
    private boolean checkRepairCodeExists(String repairCode) {
        try {
            SbRepairApplication query = new SbRepairApplication();
            query.setRepairCode(repairCode);
            List<SbRepairApplication> existingList = repairApplicationMapper.selectSbRepairApplicationList(query);
            return existingList != null && !existingList.isEmpty();
        } catch (Exception e) {
            log.error("检查报修单编号是否存在失败", e);
            return false;
        }
    }
    
    /**
     * 接单处理
     */
    @Override
    public boolean acceptRepairApplication(Integer repairId) {
        try {
            SbRepairApplication application = repairApplicationMapper.selectSbRepairApplicationById(repairId);
            if (application == null) {
                log.error("报修单不存在，ID: {}", repairId);
                return false;
            }
            
            // 检查当前状态是否允许接单
            if (!"pending".equals(application.getStatus())) {
                log.error("报修单状态不允许接单，当前状态: {}, ID: {}", application.getStatus(), repairId);
                return false;
            }
            
                // 更新报修单状态
                application.setStatus("processing");
                application.setUpdateTime(DateUtils.getNowDate());
                application.setUpdateBy(SecurityUtils.getUsername());
                application.setHandlePerson(SecurityUtils.getUsername());
                application.setHandleTime(DateUtils.getNowDate());
                
                boolean updated = repairApplicationMapper.updateSbRepairApplication(application) > 0;
                if (updated) {
                // 自动更新设备状态为维修中
                updateEquipmentStatusToRepair(application.getEquipmentId());
                
                log.info("接单成功，报修单ID: {}, 状态更新为: processing", repairId);
                    return true;
            }
            return false;
        } catch (Exception e) {
            log.error("接单失败，报修单ID: {}", repairId, e);
            return false;
        }
    }

    /**
     * 更新设备状态为维修中
     * 
     * @param equipmentId 设备ID
     */
    private void updateEquipmentStatusToRepair(Integer equipmentId) {
        try {
            if (equipmentId == null) {
                log.warn("设备ID为空，跳过设备状态更新");
                return;
            }
            
            // 调用设备Service
            ISbEquipmentService equipmentService = SpringUtils.getBean(ISbEquipmentService.class);
            if (equipmentService != null) {
                Long equipmentIdLong = Long.valueOf(equipmentId);
                int updateResult = equipmentService.updateStatus(equipmentIdLong, "2", "设备报修，进入维修状态");
                if (updateResult > 0) {
                    log.info("设备状态更新为维修中成功，设备ID: {}", equipmentId);
                } else {
                    log.error("设备状态更新为维修中失败，设备ID: {}", equipmentId);
                }
            } else {
                log.error("获取设备服务失败");
            }
        } catch (Exception e) {
            log.error("更新设备状态为维修中失败，设备ID: {}", equipmentId, e);
        }
    }
    
    /**
     * 取消报修单
     */
    @Override
    public boolean cancelRepairApplication(Integer repairId, String reason) {
        try {
            SbRepairApplication application = repairApplicationMapper.selectSbRepairApplicationById(repairId);
            if (application == null) {
                log.error("报修单不存在，ID: {}", repairId);
                return false;
            }
            
            // 检查当前状态是否允许取消
            if ("completed".equals(application.getStatus()) || "canceled".equals(application.getStatus())) {
                log.error("报修单状态不允许取消，当前状态: {}, ID: {}", application.getStatus(), repairId);
                return false;
            }
            
                application.setStatus("canceled");
                application.setRemark(reason);
                application.setUpdateTime(DateUtils.getNowDate());
                application.setUpdateBy(SecurityUtils.getUsername());
                application.setCloseTime(DateUtils.getNowDate());
            
            boolean result = repairApplicationMapper.updateSbRepairApplication(application) > 0;
            if (result) {
                // 由于报修单和维修单使用同一个表，不需要同步取消维修单
                log.info("取消报修单成功，ID: {}, 原因: {}", repairId, reason);
            }
            return result;
        } catch (Exception e) {
            log.error("取消报修单失败，ID: {}", repairId, e);
            return false;
        }
    }
    
    /**
     * 添加测试数据
     */
    private void addTestData() {
        try {
            // 检查是否已存在测试数据
            SbRepairApplication query = new SbRepairApplication();
            query.setEquipmentName("测试设备A");
            List<SbRepairApplication> existingList = repairApplicationMapper.selectSbRepairApplicationList(query);
            if (!existingList.isEmpty()) {
                log.info("已存在测试数据，无需重复添加");
                return;
            }
            
            // 生成唯一编号
            R<String> codeResult = generateCode();
            String repairCode = codeResult.getCode() == 200 ? 
                codeResult.getData() : "REP" + DateUtils.dateTimeNow("yyyyMMdd") + "0001";
            
            SbRepairApplication testData = new SbRepairApplication();
            testData.setRepairCode(repairCode);
            testData.setEquipmentId(1);
            testData.setEquipmentCode("EQPT001");
            testData.setEquipmentName("测试设备A");
            testData.setFaultType("电气故障");
            testData.setFaultLevel("一般");
            testData.setFaultDescription("设备主控面板无反应，可能是电源问题");
            testData.setFaultTime(DateUtils.getNowDate());
            testData.setReportPerson("张三");
            testData.setReportPhone("13800138000");
            testData.setReportTime(DateUtils.getNowDate());
            testData.setPriority("normal");
            testData.setStatus("pending");
            testData.setCreateBy("admin");
            testData.setCreateTime(DateUtils.getNowDate());
            testData.setIsDelete("0");
            testData.setRemark("这是一条测试数据");
            
            repairApplicationMapper.insertSbRepairApplication(testData);
            log.info("添加测试数据成功，编号: {}", repairCode);
            
            // 添加第二条测试数据
            try {
                Thread.sleep(100); // 确保时间戳不同
                
                // 生成第二个唯一编号
                codeResult = generateCode();
                repairCode = codeResult.getCode() == 200 ? 
                    codeResult.getData() : "REP" + DateUtils.dateTimeNow("yyyyMMdd") + "0002";
                
                SbRepairApplication testData2 = new SbRepairApplication();
                testData2.setRepairCode(repairCode);
                testData2.setEquipmentId(2);
                testData2.setEquipmentCode("EQPT002");
                testData2.setEquipmentName("测试设备B");
                testData2.setFaultType("机械故障");
                testData2.setFaultLevel("紧急");
                testData2.setFaultDescription("设备传送带卡住，需要立即维修");
                testData2.setFaultTime(DateUtils.getNowDate());
                testData2.setReportPerson("李四");
                testData2.setReportPhone("13900139000");
                testData2.setReportTime(DateUtils.getNowDate());
                testData2.setPriority("urgent");
                testData2.setStatus("pending");
                testData2.setCreateBy("admin");
                testData2.setCreateTime(DateUtils.getNowDate());
                testData2.setIsDelete("0");
                testData2.setRemark("这是第二条测试数据");
                
                repairApplicationMapper.insertSbRepairApplication(testData2);
                log.info("添加第二条测试数据成功，编号: {}", repairCode);
            } catch (Exception e) {
                log.warn("添加第二条测试数据失败，但不影响第一条: {}", e.getMessage());
            }
            
            log.info("初始化了 2 条测试报修单数据");
        } catch (Exception e) {
            log.error("添加测试数据失败", e);
        }
    }
} 